//-------------------------------------------------------------------
//	Copyright (c) 2012-2014 Zhirnov Andrey
//	This file is part of the "UXGEN-ES" project.
//	See copyright notice in "Engine.h".
//-------------------------------------------------------------------

#include "Graphics/Systems/GraphicsEngine.h"
#include "Graphics/Systems/BatchRender.h"

// GL shell //
#include "Graphics/GLshell/FrameBuffer.h"

// Resources //
#include "Graphics/Resources/Texture.h"
#include "Graphics/Resources/Material.h"
#include "Graphics/Resources/Model.h"
#include "Graphics/Resources/Program.h"
#include "Graphics/Resources/Font.h"


namespace Engine
{
namespace Graphics
{
	
/*
=================================================
	constructor
=================================================
*/
	GraphicsEngine::GraphicsEngine (const EngineSubSystemsRef ess) :
		BaseObject(ess), _viewport(ess), _stateMngr(ess), _render2D(ess), _render3D(ess),
		_shaderMngr(ess), _initialized(false)
	{
		ESS()->SetGraphicsEngine( this );

		ESS()->GetEventSystem()->AttachEventListener( 
			DelegateBuilder::Create( GraphicsEnginePtr(this), &GraphicsEngine::_OnWindowEvent ),		ESystemEvent::WINDOW );
		
		ESS()->GetEventSystem()->AttachEventListener(
			DelegateBuilder::Create( GraphicsEnginePtr(this), &GraphicsEngine::_OnApplicationEvent ),	ESystemEvent::APPLICATION );

		_currentViewport = &_viewport;
	}
		
/*
=================================================
	destructor
=================================================
*/
	GraphicsEngine::~GraphicsEngine ()
	{
		Ptr< ResourceManager >	rm = ESS()->GetResourceManager();
		
		if ( rm.IsNotNull() )
		{
			_programLoader.Unregister( rm );
			_textureLoader.Unregister( rm );
			_spriteLoader.Unregister( rm );
			_fontLoader.Unregister( rm );
		}

		if ( ESS()->GetEventSystem().IsNotNull() )
		{
			ESS()->GetEventSystem()->DetachEventListener( 
				DelegateBuilder::Create( GraphicsEnginePtr(this), &GraphicsEngine::_OnWindowEvent ),		ESystemEvent::WINDOW );
		
			ESS()->GetEventSystem()->DetachEventListener(
				DelegateBuilder::Create( GraphicsEnginePtr(this), &GraphicsEngine::_OnApplicationEvent ),	ESystemEvent::APPLICATION );
		}

		ESS()->SetGraphicsEngine( null );
	}
	
/*
=================================================
	Init
=================================================
*/
	bool GraphicsEngine::Init (const VideoSettings &vs)
	{
		if ( _initialized )
		{
			WARNING( "reinitialization!" );
			return true;
		}

		_videoSettings = vs;

		CHECK_ERR( ESS()->GetApplication()->GetPlatform()->InitRender( _videoSettings ) );
		_viewport.Setup2DMode( rect(-1.0f, -1.0f, 1.0f, 1.0f) );

		_initialized = true;
		return _initialized;
	}
	
/*
=================================================
	InitResources
=================================================
*/
	void GraphicsEngine::InitResources ()
	{
		Ptr< ResourceManager >	rm = ESS()->GetResourceManager();
		
		CHECK_ERR( rm.IsNotNull(), void() );

		_programLoader.Register( rm );
		_textureLoader.Register( rm );
		_spriteLoader.Register( rm );
		_fontLoader.Register( rm );
	}
	
/*
=================================================
	_OnResized
=================================================
*/
	void GraphicsEngine::_OnResized ()
	{
		const ivec2	new_size = ESS()->GetApplication()->GetPlatform()->GetDisplay().Resolution();

		_stateMngr.OnResized( new_size );

		_viewport.SetViewport( ivec4( 0, 0, new_size.x, new_size.y ) );
		_viewport.Setup2DMode( _viewport.GetMode2D() );
	}
	
/*
=================================================
	_Destroy
=================================================
*/
	void GraphicsEngine::_Destroy ()
	{
		_fontLoader.Destroy();
	}

/*
=================================================
	_OnWindowEvent
=================================================
*/
	void GraphicsEngine::_OnWindowEvent (const SysEvent &ev)
	{
		if ( ev.window.type == SysEvent::Window::RESIZED )
		{
			_OnResized();
		}
	}
	
/*
=================================================
	_OnApplicationEvent
=================================================
*/
	void GraphicsEngine::_OnApplicationEvent (const SysEvent &ev)
	{
		switch ( ev.app.type )
		{
			case SysEvent::Application::SURFACE_CREATED :
				_stateMngr.Init();
				break;

			case SysEvent::Application::SURFACE_DESTROYED :
				_Destroy();
				break;
		}
	}


}	// Graphics
}	// Engine